
`timescale 1 ns / 10 ps

//  *************************************************************************
//  File : crc32galstep16c
//  *************************************************************************
//  This program is controlled by a written license agreement.
//  Unauthorized Reproduction or Use is Expressly Prohibited. 
//  Copyright (c) 2000 Morethanip
//  info@morethanip.com
//  *************************************************************************
//   Version:    $Id: crc32galstep16c.v,v 1.1 2009/07/09 00:23:23 dk Exp $
//   Author:     Morethanip, Daniel Koehler
//  *************************************************************************
//  Description:
// 
//  16 Bit Galois Field Multiplier
//  *************************************************************************

module crc32galstep16c (

   data,
   crc_in,
   crc_out);
   
input   [15:0] data;            //  new input data
input   [31:0] crc_in;          //  current CRC value
output  [31:0] crc_out;         //  new CRC value

wire    [31:0] crc_out; 
wire    [47:0] i; 
wire    [61:0] o1; 
wire    [31:0] o; 

assign crc_out = o;   

//  Level 1
//  crcgal16_1L1_4
//  --------------

assign i = {data, crc_in}; 
assign o1[0] = i[6] ^ i[7] ^ i[10] ^ i[0]; 
assign o1[1] = i[8] ^ i[11] ^ i[7] ^ i[1]; 
assign o1[2] = i[9] ^ i[6] ^ i[12] ^ i[2]; 
assign o1[3] = i[9] ^ i[13] ^ i[3] ^ i[10]; 
assign o1[4] = i[14] ^ i[8] ^ i[4] ^ i[11]; 
assign o1[5] = i[15] ^ i[12] ^ i[9] ^ i[5]; 
assign o1[6] = i[13] ^ i[12] ^ i[0] ^ i[4]; 
assign o1[7] = i[14] ^ i[8] ^ i[1] ^ i[5]; 
assign o1[8] = i[6] ^ i[15] ^ i[2] ^ i[9]; 
assign o1[9] = i[3] ^ i[6] ^ i[15] ^ i[4]; 
assign o1[10] = i[10] ^ i[6] ^ i[2] ^ i[5]; 
assign o1[11] = i[7] ^ i[11] ^ i[3] ^ i[6]; 
assign o1[12] = i[7] ^ i[8] ^ i[12] ^ i[0]; 
assign o1[13] = i[13] ^ i[9] ^ i[1] ^ i[8]; 
assign o1[14] = i[14] ^ i[10] ^ i[2] ^ i[6]; 
assign o1[15] = i[11] ^ i[3] ^ i[15] ^ i[7]; 
assign o1[16] = i[11] ^ i[12] ^ i[3] ^ i[8]; 
assign o1[17] = i[13] ^ i[10] ^ i[9] ^ i[2]; 
assign o1[18] = i[14] ^ i[0] ^ i[6] ^ i[11]; 
assign o1[19] = i[1] ^ i[12] ^ i[15] ^ i[3]; 
assign o1[20] = i[13] ^ i[10] ^ i[1] ^ i[2]; 
assign o1[21] = i[6] ^ i[12] ^ i[15] ^ i[37]; 
assign o1[22] = i[4] ^ i[13] ^ i[3] ^ i[11]; 
assign o1[23] = i[14] ^ i[4] ^ i[5] ^ i[12]; 
assign o1[24] = i[10] ^ i[13] ^ i[5] ^ i[15]; 
assign o1[25] = i[9] ^ i[14] ^ i[4] ^ i[10]; 
assign o1[26] = i[8] ^ i[14] ^ i[2] ^ i[10]; 
assign o1[27] = i[7] ^ i[13] ^ i[0] ^ i[6]; 
assign o1[28] = i[1] ^ i[7] ^ i[8] ^ i[13]; 
assign o1[29] = i[4] ^ i[14] ^ i[3] ^ i[8]; 
assign o1[30] = i[9] ^ i[5] ^ i[15] ^ i[3]; 
assign o1[31] = i[0] ^ i[14] ^ i[24]; 
assign o1[32] = i[0] ^ i[5] ^ i[29]; 
assign o1[33] = i[1] ^ i[9] ^ i[30]; 
assign o1[34] = i[2] ^ i[10] ^ i[31]; 
assign o1[35] = i[2] ^ i[15] ^ i[35]; 
assign o1[36] = i[4] ^ i[16]; 
assign o1[37] = i[5] ^ i[17]; 
assign o1[38] = i[8] ^ i[18]; 
assign o1[39] = i[7] ^ i[19]; 
assign o1[40] = i[10] ^ i[20]; 
assign o1[41] = i[11] ^ i[21]; 
assign o1[42] = i[7] ^ i[22]; 
assign o1[43] = i[13] ^ i[23]; 
assign o1[44] = i[1] ^ i[25]; 
assign o1[45] = i[4] ^ i[28]; 
assign o1[46] = i[9] ^ i[33]; 
assign o1[47] = i[12] ^ i[34]; 
assign o1[48] = i[13] ^ i[41]; 
assign o1[49] = i[11] ^ i[42]; 
assign o1[50] = i[9] ^ i[43]; 
assign o1[51] = i[12] ^ i[44]; 
assign o1[52] = i[14] ^ i[45]; 
assign o1[53] = i[6] ^ i[47]; 

//  rerouted inputs that are to be grouped at level 2
//  -------------------------------------------------

assign o1[54] = i[26]; //  row: 10
assign o1[55] = i[27]; //  row: 11
assign o1[56] = i[32]; //  row: 16
assign o1[57] = i[36]; //  row: 20
assign o1[58] = i[38]; //  row: 22
assign o1[59] = i[39]; //  row: 23
assign o1[60] = i[40]; //  row: 24
assign o1[61] = i[46]; //  row: 30

//  Level 2 final outputs
//  crcgal16_1L2_4
//  ---------------------

assign o[0] = o1[0] ^ o1[36]; 
assign o[1] = o1[1] ^ o1[37]; 
assign o[2] = o1[2] ^ o1[38]; 
assign o[3] = o1[3] ^ o1[39]; 
assign o[4] = o1[4] ^ o1[40]; 
assign o[5] = o1[5] ^ o1[41]; 
assign o[6] = o1[6] ^ o1[42]; 
assign o[7] = o1[7] ^ o1[43]; 
assign o[8] = o1[31] ^ o1[8]; 
assign o[9] = o1[44] ^ o1[9]; 
assign o[10] = o1[10] ^ o1[54]; 
assign o[11] = o1[11] ^ o1[55]; 
assign o[12] = o1[12] ^ o1[45]; 
assign o[13] = o1[32] ^ o1[13]; 
assign o[14] = o1[33] ^ o1[14]; 
assign o[15] = o1[34] ^ o1[15]; 
assign o[16] = o1[0] ^ o1[16] ^ o1[56]; 
assign o[17] = o1[6] ^ o1[1] ^ o1[46]; 
assign o[18] = o1[7] ^ o1[17] ^ o1[47]; 
assign o[19] = o1[18] ^ o1[35] ^ o1[3]; 
assign o[20] = o1[18] ^ o1[19] ^ o1[57]; 
assign o[21] = o1[20] ^ o1[21]; 
assign o[22] = o1[14] ^ o1[22] ^ o1[58]; 
assign o[23] = o1[15] ^ o1[23] ^ o1[59]; 
assign o[24] = o1[12] ^ o1[24] ^ o1[60]; 
assign o[25] = o1[1] ^ o1[25] ^ o1[48]; 
assign o[26] = o1[26] ^ o1[5] ^ o1[49]; 
assign o[27] = o1[6] ^ o1[15] ^ o1[50]; 
assign o[28] = o1[27] ^ o1[7] ^ o1[51]; 
assign o[29] = o1[28] ^ o1[8] ^ o1[52]; 
assign o[30] = o1[8] ^ o1[29] ^ o1[61]; 
assign o[31] = o1[30] ^ o1[53]; 

endmodule
